﻿using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using XrmLibrary.Enums;
using XrmLibrary.Exceptions;
using XrmLibrary.MessageStrings;
using XrmLibrary.ConfigFile;
using XrmLibrary.Adapters;
using XrmLibrary.Credentials;

namespace XrmLibrary.Configurations
{
    internal class CrmConfigurationList : List<CrmConfigurationBase>
    {
        public CrmConfigurationBase this[String configurationName]
        {
            get
            {
                foreach (CrmConfigurationBase crmConfiguration in this)
                {

                    if(crmConfiguration.GetConfigurationName() == configurationName)
                    {
                        return crmConfiguration;
                    }
                }
                throw new XrmLibraryException("No CrmConfiguration exists for the supplied name.");
            }
        }

        public void ValidateCrmConfigurationExists(int index)
        {
            if (index >= this.Count)
            {
                throw new ArgumentException(ErrorStrings.NoServiceExistsForIndex);
            }
        }

        public void ValidateCrmConfigurationExists(string configurationName)
        {
            if(this[configurationName] == null)
            {
                throw new ArgumentException(ErrorStrings.NoServiceExistsForName);
            }
        }
        
        public void AddConfigurations(XrmLibraryConfigSection configuration)
        {
            if (configuration.CredentialStore == CredentialStoreType.config)
            {
                AddCrm2011Configurations(configuration.CrmServiceConfigurations);
                AddAdapterConfigurations(configuration.AdapterConfigurations);
            }
            else if(configuration.CredentialStore == CredentialStoreType.database)
            {
                LoadConfigurationsFromDatabase(configuration.ConnectionString, configuration.AppName);
            }
        }


        private void AddCrm2011Configurations(CrmServiceConfigurationsCollection crmConfigurations)
        {
            foreach(CrmServiceConfigurationElement serviceConfig in crmConfigurations)
            {
                AddCrm2011Configuration(serviceConfig);
            }
        }

        internal void AddCrm2011Configuration(CrmServiceConfigurationElement serviceConfig)
        {
            AdapterConfiguration adapterConfig = new AdapterConfiguration(serviceConfig);
            CrmConfiguration crmConfiguration = new CrmConfiguration();
            crmConfiguration.Instantiate(adapterConfig);
            Add(crmConfiguration);
        }

        private void AddAdapterConfigurations(AdapterConfigurationsCollection adapterConfigurations)
        {
            foreach(AdapterCollection adapterCollection in adapterConfigurations)
            {
                AdapterRuntimeLoader adapterRuntimeLoader = AdapterRuntimeLoader.Instantiate(adapterCollection.AssemblyName, adapterCollection.AssemblyPath);
                foreach(AdapterInstanceCollection adapterInstance in adapterCollection)
                {
                    AdapterInstanceConverter adapterInstanceConverter = AdapterInstanceConverter.Instantiate(adapterInstance);
                    AdapterConfiguration adapterConfig = adapterInstanceConverter.GetDynamicAdapterConfiguration();
                    CrmConfigurationBase crmConfiguration = adapterRuntimeLoader.InstantiateCrmConfiguration(adapterConfig);
                    Add(crmConfiguration);
                }
            }
        }

        private void LoadConfigurationsFromDatabase(string connectionString, string appName)
        {
            using (SqlCredentialStore sqlCredentialStore = SqlCredentialStore.Instantiate(connectionString, appName))
            {
                CrmServiceConfigurationsCollection crmConfigurations = sqlCredentialStore.RetrieveCrmServiceConfigurations();
                AddCrm2011Configurations(crmConfigurations);
            }
        }

        public void LoadAllCrmConfigurations()
        {
            foreach(CrmConfigurationBase crmConfiguration in this)
            {
                crmConfiguration.Load();
            }
        }
    }
}
